<?php
/**
 * Class to user access (login, register, logout, etc)
 *
 * =========================================================================================
 *
 * @author mr.trieu
 *         @thanks Nick Papanotas <nikolas@webdigity.com>
 * @license http://opensource.org/licenses/gpl-license.php GNU General Public
 *          License (GPL)
 *
 *
 *
 *          =========================================================================================
 *
 *          include('access.class.php');
 *          $user = new flexibleAccess();
 *
 */
defined('PT_ACCESS') or die('No direct access');

/*
 * Flexible Access - The main class
 */

class user extends BaseControllers{
	protected $registry;

	/* Settings */
	/*
	 * The database table that holds all the information
	 * var string
	 */
	var $dbTable = 'users';
	/*
	 * The session variable ($_SESSION[$sessionVariable]) which will hold the
	 * data while the user is logged on var string
	 */
	var $sessionVariable = 'userSessionValue';
	/*
	 * Those are the fields that our table uses in order to fetch the needed
	 * data. The structure is 'fieldType' => 'fieldName' var array
	 */
	var $tbFields = array(
			'userID'=>'u_id',
			'login'=>'u_username',
			'pass'=>'u_password',
			'email'=>'u_email',
			'active'=>'u_active',
			'rights'=>'u_rights',
			'language'=>'u_lang'
	);
	/*
	 * When user wants the system to remember him/her, how much time to keep the
	 * cookie? (seconds) var int
	 */
	var $remTime = 2592000; // One month
	/*
	 * The name of the cookie which we will use if user wants to be remembered
	 * by the system var string
	 */
	var $remCookieName = 'ckSavePass';
	/*
	 * The cookie domain var string
	 */
	var $remCookieDomain = '';
	/*
	 * The method used to encrypt the password. It can be sha1, md5 or nothing
	 * (no encryption) var string
	 */
	var $passMethod = 'sha1';
	/*
	 * Display errors? Set this to true if you are going to seek for help, or
	 * have troubles with the script var bool
	 */
	var $displayErrors = true;

	/* Do not edit after this line */
	var $userID;
	var $userData = array();
	var $langCode = '';

	/*
	 * Class Constructure @param array $settings @return void
	 */
	function __construct($registry, $settings = ''){
		$this->registry = $registry;

		if (is_array($settings)){
			foreach ($settings as $k=>$v){
				if (!isset($this->{$k}))
					die('Property ' . $k . ' does not exists. Check your settings.');
				$this->{$k} = $v;
			}
		}

		$this->remCookieDomain = $this->remCookieDomain == '' ? $_SERVER['HTTP_HOST'] : $this->remCookieDomain;

		if (!isset($_SESSION))
			session_start();

		if (!empty($_SESSION[$this->sessionVariable])){
			$this->loadUser($_SESSION[$this->sessionVariable]);
		}

		// Maybe there is a cookie?
		if (isset($_COOKIE[$this->remCookieName]) && !$this->is_loaded()){
			// echo 'I know you<br />';
			$u = unserialize(base64_decode($_COOKIE[$this->remCookieName]));
			$this->login($u['uname'], $u['password']);
		}
	}

	/*
	 * Login function @param string $uname @param string $password @param bool
	 * $loadUser @return bool
	 */
	function login($uname, $password, $remember = false, $loadUser = true){

		$uname = $this->escape($uname);
		$password = $originalPassword = $this->escape($password);

		switch (strtolower($this->passMethod)){
			case 'sha1':
				$password = SHA1($password);
			break;
			case 'md5':
				$password = MD5($password);
			break;
			case 'nothing':
				$password = $password;
		}

		$res = "SELECT * FROM `{$this->dbTable}` WHERE `{$this->tbFields['login']}` = '$uname' AND `{$this->tbFields['pass']}` = '$password' LIMIT 1";

		if ($this->db->numRows($res) == 0)
			return false;

		if ($loadUser){

			$this->userID = $this->db->fetchOne($res);

			$_SESSION[$this->sessionVariable] = $this->userID;

			if ($remember){
				$cookie = base64_encode(serialize(array(
						'uname'=>$uname,
						'password'=>$originalPassword
				)));
				$a = setcookie($this->remCookieName, $cookie, time() + $this->remTime, '/', $this->remCookieDomain);
			}
		}

		return true;
	}

	/*
	 * A function that is used to load one user's data @access private @param
	 * string $userID @return bool
	 */
	function loadUser($userID = 0){

		$langs = array();

		$res = "SELECT * FROM `{$this->dbTable}` WHERE `{$this->tbFields['userID']}` = '" . $this->escape($userID) . "' LIMIT 1";

		if ($this->db->numRows($res) == 0)
			return false;

		$this->userData = $this->db->fetchAll($res);
		$this->userID = $userID;

		$_SESSION[$this->sessionVariable] = $this->userID;

		$langs = explode(',', $this->userData[0]['u_lang']);

		// Set default language
		$this->langCode = $langs[0];

		return true;
	}

	/*
	 * Produces the result of addslashes() with more safety @access private
	 * @param string $str @return string
	 */
	function escape($str){
		$str = get_magic_quotes_gpc() ? stripslashes($str) : $str;
		$str = mysql_real_escape_string($str);
		return $str;
	}

	/*
	 * Is the user loaded? @ return bool
	 */
	function is_loaded(){
		return empty($this->userID) ? false : true;
	}

	/*
	 * Is the user admin @ return bool
	 */
	function is_admin($isAdmin = 0){
		return empty($isAdmin) ? false : true;
	}

	/*
	 * Logout function param string $redirectTo @return bool
	 */
	function logout($redirectTo = ''){

		$this->userData = '';

		setcookie($this->remCookieName, '', time() - 3600);

		unset($_SESSION[$this->sessionVariable]);
		unset($_SESSION['codeLang']);
		session_destroy();

		if ($redirectTo != '' && !headers_sent()){
			header('HTTP/1.1 301 Moved Permanently');
			header('Location: ' . $redirectTo);
			exit(); // To ensure security
		}
	}

	/*
	 * Function to determine if a property is true or false param string $prop
	 * @return bool
	 */
	function is($prop){
		return $this->get_property($prop) == 1 ? true : false;
	}

	/*
	 * Get a property of a user. You should give here the name of the field that
	 * you seek from the user table @param string $property @return string
	 */
	function get_property($property){
		if (empty($this->userID))
			$this->error('No user is loaded', __LINE__);

		if (!isset($this->userData[$property]))
			$this->error('Unknown property <b>' . $property . '</b>', __LINE__);

		return $this->userData[$property];
	}

	/*
	 * Creates a user account. The array should have the form 'database field'
	 * => 'value' @param array $data return int
	 */
	function insertUser($data){

		global $db;

		if (!is_array($data))
			$this->error('Data is not an array', __LINE__);

		switch (strtolower($this->passMethod)){
			case 'sha1':
				$password = SHA1($data[$this->tbFields['pass']]);
			break;
			case 'md5':
				$password = MD5($data[$this->tbFields['pass']]);
			break;
			case 'nothing':
				$password = $data[$this->tbFields['pass']];
		}

		foreach ($data as $k=>$v){
			$data[$k] = $this->escape($v);
		}

		$data[$this->tbFields['pass']] = $password;

		return $db->insert($this->dbTable, $data);
	}

	function updateUser($uid, $data){
		global $db;

		if (!is_array($data))
			$this->error('Data is not an array', __LINE__);

		if (array_key_exists('u_password', $data)){
			switch (strtolower($this->passMethod)){
				case 'sha1':
					$password = SHA1($data[$this->tbFields['pass']]);
					break;
				case 'md5':
					$password = MD5($data[$this->tbFields['pass']]);
					break;
				case 'nothing':
					$password = $data[$this->tbFields['pass']];
			}

			$data[$this->tbFields['pass']] = $password;
		}

		foreach ($data as $k=>$v){
			$data[$k] = $this->escape($v);
		}

		$where = 'u_id = ' . $uid;

		$db->update($this->dbTable, $data, $where);

		return TRUE;
	}

	/**
	 * Update access module for a user account
	 * for Insert/Update a user account
	 */
	function updateModules($type, $uid, $mods){

		global $db;
		$rights = '';

		if (!is_array($mods))
			$this->error('Data is not an array', __LINE__);

		if (is_array($mods)){
			foreach ($mods as $key){
				$rights .= $key . ',';
			}
		}
		if (substr($rights, strlen($rights) - 1, 1) == ',')
			$rights = substr($rights, 0, strlen($rights) - 1);

		if ($type == 'in'){
			$data = array(
					'md_userID'=>$uid,
					'md_mods'=>$rights
			);

			return $db->insert('modules', $data);
		}elseif ($type == 'up'){
			$data = array(
					'md_mods'=>$rights
			);
			$where = 'md_userID = ' . $uid;

			return $db->update('modules', $data, $where);
		}
	}

	/*
	 * Activates the user account @return bool
	 */
	function activate(){

		global $db;

		if (empty($this->userID))
			$this->error('No user is loaded', __LINE__);

		if ($this->is_active())
			$this->error('Allready active account', __LINE__);

			// $data = "UPDATE `{$this->dbTable}` SET
			// {$this->tbFields['active']} = 1 WHERE
			// `{$this->tbFields['userID']}` =
			// '" . $this->escape($this->userID) . "'";

		$data = array(
				$this->tbFields['active']=>1
		);
		$where = '"' . $this->tbFields['userID'] = $this->escape($this->userID) . '"';

		$db->update($this->dbTable, $data, $where);

		if (@mysql_affected_rows() == 1){
			$this->userData[$this->tbFields['active']] = true;

			return true;
		}

		return false;
	}

	/*
	 * Check current password of a user account
	 * @return true/false
	 * */
	function checkpass($pass){
		if (empty($pass))
			$this->error('Password is missing.', __LINE__);

		global $db;

		switch (strtolower($this->passMethod)){
			case 'sha1':
				$password = SHA1($pass);
				break;
			case 'md5':
				$password = MD5($pass);
				break;
			case 'nothing':
				$password = $pass;
		}

		$Qry = 'SELECT u_id
				FROM users
				WHERE u_password = "' . $password . '" AND u_id = ' . $this->userID;

		if ($db->numRows($Qry) == 0)
			return false;
		else
			return true;
	}

	/*
	 * Is the user an active user? @return bool
	 */
	function is_active(){
		return $this->userData[$this->tbFields['active']];
	}

	/*
	 * Creates a random password. You can use it to create a password or a hash
	 * for user activation param int $length param string $chrs return string
	 */
	function randomPass($length = 10, $chrs = '1234567890qwertyuiopasdfghjklzxcvbnm!@#$%^&*()_-+{}[]<>,.?/=:;'){

		$pwd = '';

		for ($i = 0; $i < $length; $i++){
			$pwd .= $chrs{mt_rand(0, strlen($chrs) - 1)};
		}

		return $pwd;
	}

	function randomKey($length = 10, $chrs = '1234567890qwertyuiopasdfghjklzxcvbnm'){

		$pwd = '';

		for ($i = 0; $i < $length; $i++){
			$pwd .= $chrs{mt_rand(0, strlen($chrs) - 1)};
		}

		return $pwd;
	}

	/*
	 * Error holder for the class @access private @param string $error @param
	 * int $line @param bool $die @return bool
	 */
	function error($error, $line = '', $die = false){
		if ($this->displayErrors)
			echo '<b>Error: </b>' . $error . '<br /><b>Line: </b>' . ($line == '' ? 'Unknown' : $line) . '<br />';
		if ($die)
			exit();
		return false;
	}
}

/**
 * Permissions class.
 */
class permr{
	/**
	 * Read constant.
	 *
	 * @var int
	 */
	const READ = 1;

	/**
	 * Edit constant.
	 *
	 * @var int
	 */
	const EDIT = 2;

	/**
	 * Publish constant.
	 *
	 * @var int
	 */
	const PUBLISH = 4;

	/**
	 * Delete constant.
	 *
	 * @var int
	 */
	const DELETE = 8;

	/**
	 * Echoes permissions.
	 *
	 * @param array $roles
	 *        	Roles array
	 * @param array $perms
	 *        	Permissions array
	 */
	static public function checkPerms($roles, $perms){

		$a = '';

		foreach ($roles as $k=>$v){
			foreach ($perms as $pk=>$pv){
				if ($v & $pv)
					$a .= $pk . ',';
			}
		}

		if (substr($a, strlen($a) - 1, 1) == ',')
			$a = substr($a, 0, strlen($a) - 1);

		$rights = explode(',', $a);

		return $rights;
	}

	/*
	 * Check user group @return Permissions array
	 */
	static public function userGroup($perms = array(), $userID = 0){

		switch ($userID){
			case 1:
				global $guest;

				$roles = array(
						'Guest'=>$guest
				);
			break;
			case 3:
				global $editor;

				$roles = array(
						'Editor'=>$editor
				);
			break;
			case 5:
				global $publisher;

				$roles = array(
						'Publisher'=>$publisher
				);
			break;
			case 7:
				global $moderator;

				$roles = array(
						'Moderator'=>$moderator
				);
			break;
			case 15:
				global $admin;

				$roles = array(
						'Administrator'=>$admin
				);
			break;
			default:
				global $guest;

				$roles = array(
						'Guest'=>$guest
				);
			break;
		}

		return self::checkPerms($roles, $perms);
	}
}

/**
 * Permissions Modules
 */
class permm{

	/*
	 * Check user access module @ return module array
	 */
	public static function checkMod($userLevel = 1, $userID = 0, $mods = array()){

		if (count($mods) == 0)
			die('Can not access module');

		if ($userLevel == 15)
			return $mods;
		else{
			global $db;

			$Qry = "SELECT md_mods
					FROM modules
					WHERE md_userID = " . $userID;
			$row = $db->fetchRow($Qry);

			return explode(',', $row[0]);
		}
	}
}
